﻿using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Linq;
using System.Diagnostics;
using System;
using RoiControllers;
using System.Drawing.Drawing2D;

namespace UserControls
{
    public partial class UImageWindow : UImage
    {
        #region 字段|属性
        #region 字段
        private int nextId = 0;             //形状ID
        private ShapeType ShapeType;        //形状类型
        private ShapeBase _currentShape;    //当前形状图形
        private ShapeOperateMode _shapeOperateMode;   //当前图形的操作模式
        private List<ShapeBase> shapeFigureList;      //形状图形列表
        #endregion

        #region 属性
        /// <summary> 形状列表 </summary>
        [Category("UserDefine")]
        [Description("形状图形列表")]
        public List<ShapeBase> ShapeFigureList { get => shapeFigureList; }

        /// <summary> 形状列表 </summary>
        [Category("UserDefine")]
        [Description("形状绘制模式")]
        public ShapeOperateMode ShapeOperateMode
        { 
            get => _shapeOperateMode; 
            set => _shapeOperateMode = value; 
        }
        #endregion
        #endregion

        #region 构造函数
        public UImageWindow()
        {
            DoubleBuffered = true;
            shapeFigureList = new List<ShapeBase>();
            ImagePositionChanged += OnImagePosition;
        }
        private void OnImagePosition(PointF pointF)
        {
            Debug.WriteLine($"{pointF}");
        }
        #endregion

        #region 附加方法
        /// <summary> 附加指定的形状图形到窗体 </summary>
        public void AttachShapeToWindow(ShapeBase shape)
        {
            shape.ExecuteAttachCallback();
            AddShape(shape);
            this.Invalidate();
        }
        /// <summary> 移除窗体上指定的形状图形 </summary>
        public void DetachShapeFormWindow(ShapeBase shape)
        {
            ShapeBase result = shapeFigureList.FirstOrDefault(obj => obj.Name.Equals(shape.Name));
            if (result != null)
            {
                shape.ExecuteDetachCallback();
                shapeFigureList.Remove(shape);
                this.Invalidate();
            }
        }
        /// <summary> 移除窗体上选中的形状图形 </summary>
        public void DetachShapeFormWindow()
        {
            if (_currentShape != null)
            {
                ShapeBase result = shapeFigureList.FirstOrDefault(obj => obj.Name.Equals(_currentShape.Name));
                if (result != null)
                {
                    result.ExecuteDetachCallback();
                    shapeFigureList.Remove(result);
                    this.Invalidate();
                }
            }
        }
        #endregion

        #region 区域截取
        /// <summary> 获取选择的区域图像：根据区域类型判断 </summary>
        public List<System.Drawing.Image> GetSelectedRegionImage()
        {
            List<System.Drawing.Image> imageList = new List<System.Drawing.Image>();
            foreach (ShapeBase shape in ShapeFigureList)
            {
                switch (shape.Type)
                {
                    case ShapeType.Rectangle:
                        imageList.Add(GetSelectedImageRegion(shape));
                        break;
                    case ShapeType.Rectangle2:
                        imageList.Add(GetSelectedImageRegionWithAngle(shape));
                        break;
                    case ShapeType.Circle:
                        imageList.Add(GetSelectedImageRegionCircle(shape));
                        break;
                    case ShapeType.Ellipse:
                        break;
                    case ShapeType.Polygon:
                        break;
                    case ShapeType.None:
                        break;
                    default:
                        break;
                }
            }
            return imageList;
        }

        /// <summary> 获取选择的区域图像：根据区域类型判断 </summary>
        public Image GetSelectedRegionImage(ShapeBase shape)
        {
            switch (shape.Type)
            {
                case ShapeType.Rectangle:
                    return GetSelectedImageRegion(shape);
                case ShapeType.Rectangle2:
                    return GetSelectedImageRegionWithAngle(shape);
                case ShapeType.Circle:
                    return GetSelectedImageRegionCircle(shape);
                case ShapeType.Ellipse:
                    break;
                case ShapeType.Polygon:
                    break;
                case ShapeType.None:
                    break;
                default:
                    break;
            }
            return null;
        }
        /// <summary> 获取选择的图像区域图像:矩形区域 </summary>
        public Image GetSelectedImageRegion(ShapeBase shape)
        {
            if (Image == null) return null;
            RectangleF imageRegion = new RectangleF(0, 0, Image.Width, Image.Height);
            RectangleF intersect = RectangleF.Intersect(shape.Region, imageRegion);
            if (intersect.IsEmpty) return null;
            // 创建目标位图并绘制所选区域
            Bitmap result = new Bitmap((int)intersect.Width, (int)intersect.Height);
            using (Graphics g = Graphics.FromImage(result))
            {
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                g.DrawImage(Image, new Rectangle(0, 0, result.Width, result.Height), intersect, GraphicsUnit.Pixel);
            }
            return result;
        }
        /// <summary> 获取选择的图像区域图像:旋转矩形区域 </summary>
        public Image GetSelectedImageRegionWithAngle(ShapeBase shape)
        {
            if (Image == null) return null;
            PointF[] points = GetRectangleCorners(shape.Region, shape.Angle);
            return GetFittingRegionImage(Image, points);
        }
        /// <summary> 获取选择的图像区域图像:圆形区域 </summary>
        public Image GetSelectedImageRegionCircle(ShapeBase shape)
        {
            if (Image == null) return null;
            RectangleF imageRegion = new RectangleF(0, 0, Image.Width, Image.Height);
            RectangleF intersect = RectangleF.Intersect(shape.Region, imageRegion);
            if (intersect.IsEmpty) return null;
            // 确定圆的半径（取矩形短边的一半）
            float radius = Math.Min(intersect.Width, intersect.Height) / 2;
            int diameter = (int)(radius * 2);
            // 计算圆形中心在原始图像中的位置
            PointF center = new PointF(intersect.X + intersect.Width / 2, intersect.Y + intersect.Height / 2);
            // 创建目标位图
            Bitmap result = new Bitmap(diameter, diameter);
            using (Graphics g = Graphics.FromImage(result))
            {
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                using (GraphicsPath path = new GraphicsPath())
                {
                    path.AddEllipse(0, 0, diameter, diameter);
                    g.SetClip(path);
                    // 计算源矩形（以中心点为基准，扩展半径距离）
                    RectangleF srcRect = new RectangleF(center.X - radius, center.Y - radius, diameter, diameter);
                    // 确保源矩形在图像范围内
                    srcRect.Intersect(imageRegion);
                    // 绘制图像
                    g.DrawImage(Image, new Rectangle(0, 0, diameter, diameter), srcRect, GraphicsUnit.Pixel);
                }
            }
            return result;
        }
        /// <summary> 获取所有选择的区域 </summary>
        public List<RectangleF> GetAllSelectedRegion()
        {
            List<RectangleF> intersections = new List<RectangleF>();
            RectangleF imageBounds = new RectangleF(0, 0, Image.Width, Image.Height);
            foreach (ShapeBase shape in shapeFigureList)
            {
                if (!shape.IsInterest) continue;
                RectangleF rect = RectangleF.Empty;
                switch (shape.Type)
                {
                    case ShapeType.Polygon:
                        break;
                    case ShapeType.Rectangle:
                        rect = shape.Region;
                        break;
                    case ShapeType.Rectangle2:
                        PointF[] pointFs = GetRectangleCorners(shape.Region, shape.Angle);
                        rect = GetBounds(Image, Array.ConvertAll(pointFs, p => Point.Round(p)));
                        break;
                    case ShapeType.Circle:
                        rect = shape.Region;
                        break;
                }
                RectangleF intersect = RectangleF.Intersect(rect, imageBounds);
                if (!intersect.IsEmpty)
                {
                    intersections.Add(intersect);
                }
            }
            return intersections;
        }
        /// <summary> 获取矩形角点 </summary>
        public PointF[] GetRectangleCorners(RectangleF rect,float angle)
        {
            PointF center = new PointF(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
            return ShapeBase.GetRotatedRectangleCorners(center, rect.Width, rect.Height, angle);
        }
        /// <summary> 获取图像数据，根据输入点拟合成区域，获取该区域与图像交集部分 </summary>
        public Image GetFittingRegionImage(Image image, PointF[] _points)
        {
            if (image == null) return null;
            // 创建目标位图（四边形的最小外接矩形）
            Rectangle bounds = GetBounds(image,Array.ConvertAll(_points, p => Point.Round(p)));
            Bitmap result = new Bitmap(bounds.Width, bounds.Height);
            using (Graphics g = Graphics.FromImage(result))
            {
                // 设置高质量绘制
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                // 定义源四边形和目标矩形
                PointF[] destPoints = new PointF[3]
                {
                    new PointF(0, 0),new PointF(bounds.Width, 0),new PointF(0, bounds.Height)
                };
                // 计算源四边形的相对坐标（相对于外接矩形）
                PointF[] srcPoints = new PointF[4];
                for (int i = 0; i < 4; i++)
                {
                    srcPoints[i] = new PointF( _points[i].X - bounds.X,_points[i].Y - bounds.Y);
                }
                // 使用GraphicsPath和纹理画刷绘制四边形区域
                using (GraphicsPath path = new GraphicsPath())
                {
                    path.AddPolygon(srcPoints);
                    using (TextureBrush brush = new TextureBrush(image))
                    {
                        // 调整画刷的变换矩阵以匹配四边形
                        Matrix matrix = new Matrix();
                        matrix.Translate(-bounds.X, -bounds.Y);
                        brush.Transform = matrix;
                        g.FillPath(brush, path);
                    }
                }
            }
            return result;
        }
        /// <summary> 获取最小外接矩形 </summary>
        private Rectangle GetBounds(Image image, Point[] _points)
        {
            if (image == null) return Rectangle.Empty;
            int minX = int.MaxValue, minY = int.MaxValue;
            int maxX = int.MinValue, maxY = int.MinValue;
            foreach (Point point in _points)
            {
                minX = Math.Min(minX, point.X);
                minY = Math.Min(minY, point.Y);
                maxX = Math.Max(maxX, point.X);
                maxY = Math.Max(maxY, point.Y);
            }
            // 确保边界在图像范围内
            minX = Math.Max(0, minX);
            minY = Math.Max(0, minY);
            maxX = Math.Min(image.Width, maxX);
            maxY = Math.Min(image.Height, maxY);
            return new Rectangle(minX, minY, maxX - minX, maxY - minY);
        }
        #endregion

        #region ROI绘制管理
        /// <summary> 添加形状到集合 </summary>
        private void AddShape(ShapeBase shape)
        {
            ShapeFigureList.ForEach(obj => obj.IsSelected = false);
            ShapeFigureList.Insert(0, shape);
            shape.Name = $"{nextId}";
            shape.Description = $"{shape.Type}_{nextId}";
            shape.IsSelected = true;
            nextId++;
            _currentShape = shape;
            shape.Region = ImageConvertControlCoordinate(shape.Region);
        }
        /// <summary> 绘制指定类型的形状对象 </summary>
        public void DrawingShapeObject(ShapeType shape)
        {
            ShapeType = shape;
            ShapeOperateMode = ShapeOperateMode.Drawing;
        }
        /// <summary> 设置当前选中的形状为感兴趣|不感兴趣状态 </summary>
        public void SetCurrentShapeInterest()
        {
            if (_currentShape!=null)
            {
                _currentShape.IsInterest = !_currentShape.IsInterest;
                this.Invalidate();
            }
        }
        /// <summary> 坐标系转换：图像->控件 </summary>
        public RectangleF ImageConvertControlCoordinate(RectangleF _imageRect, RectangleF rect)
        {
            return new RectangleF(
                 _imageRect.X + rect.X * _imageRect.Width / Image.Width,
                _imageRect.Y + rect.Y * _imageRect.Height / Image.Height,
                (rect.Width * _imageRect.Width / Image.Width),
                rect.Height * _imageRect.Height / Image.Height);
        }
        /// <summary> 坐标系转换：图像->控件 </summary>
        public RectangleF ImageConvertControlCoordinate(RectangleF rect)
        {
            RectangleF imageRect = GetImageDisplayRectangle();
            return ImageConvertControlCoordinate(imageRect, rect);
        }
        #endregion

        #region 事件方法重写
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (Image == null) return;
            foreach (ShapeBase shape in ShapeFigureList)
            {
                shape.DrawShapeWithHandle(e.Graphics, ImageConvertControlCoordinate(shape.Region));
            }
        }
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            this.Invalidate();
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            IsScaledImage = false;
            if (Image == null) return;
            if (e.Button == MouseButtons.Left)
            {
                //设置选中状态
                ShapeFigureList.FindAll(obj => obj.IsSelected = false);
                bool isSelected = false;
                RectangleF rectangleF;
                //遍历ROI，判断当前鼠标位置是否在ROI区域
                foreach (ShapeBase shape in ShapeFigureList)
                {
                    rectangleF = shape.Region;
                    shape.Region = ImageConvertControlCoordinate(rectangleF);
                    //是否在矩形区域内
                    if (shape.IsInRegion(e.Location))
                    {
                        //在背景
                        if (shape.IsInBackground(e.Location))
                            ShapeOperateMode = ShapeOperateMode.Move;
                        //在旋转手柄上
                        else if (shape.IsInRotateHandle(e.Location))
                        {
                            shape.IsRotating = true;
                            shape.LastLocation = e.Location;
                            ShapeOperateMode = ShapeOperateMode.Rotote;
                        }
                        //在手柄
                        else{
                            ShapeOperateMode = ShapeOperateMode.Resize;
                        }
                        LastDragPosition = e.Location;  //记录最后点位
                        isSelected = true;              //选中
                        IsDragImage = false;            //禁止拖动图像
                        IsOperateImage = false;         //禁止操作图像
                        _currentShape = shape;          //设置当前选中形状
                        shape.LastLocation = e.Location;//记录最后点位
                        shape.IsSelected = true;        //设置为选中状态
                        shape.HandleType = shape.GetHandleType(e.Location);
                        shape.Region = rectangleF;  //设置回原来的形状区域
                        shape.ExecuteSelectedCallback();    //执行选中回调
                        break;
                    }
                    shape.Region = rectangleF;
                }
                if (!isSelected) _currentShape = null;
                else
                {
                    this.Invalidate();
                    return;
                }
            }
            base.OnMouseDown(e);
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            IsDragImage = false;
            IsScaledImage = false;
            IsOperateImage = false;
            if (Image == null) return;
            ShapeOperateMode = ShapeOperateMode.None;   //形状的操作模式     
            this.Cursor = Cursors.Default;              //默认光标
            //取消旋转
            if (_currentShape!=null) _currentShape.IsRotating= false;
            //所有手柄类型None
            shapeFigureList.ForEach(shape => shape.HandleType = ShapeHandleType.None);
            this.Invalidate();
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (Image == null) return; 
            base.OnMouseMove(e);
            RectangleF rectangleF;
            PointF pointF = PointF.Empty;
            if (!IsOperateImage && !IsDragImage)
            {
                if (_currentShape != null)
                {
                    //如果有操作，重绘后直接return跳出方法
                    switch (ShapeOperateMode)
                    {
                        case ShapeOperateMode.Move:
                            rectangleF = GetImageDisplayRectangle();
                            pointF.X = (e.X - LastDragPosition.X) * Image.Width / rectangleF.Width;
                            pointF.Y = (e.Y - LastDragPosition.Y) * Image.Height / rectangleF.Height;
                            LastDragPosition = e.Location;
                            _currentShape.Move(pointF, e.Location);
                            Invalidate();
                            return;
                        case ShapeOperateMode.Resize:
                            rectangleF = GetImageDisplayRectangle();
                            pointF.X = (e.X - LastDragPosition.X) * Image.Width / rectangleF.Width;
                            pointF.Y = (e.Y - LastDragPosition.Y) * Image.Height / rectangleF.Height;
                            LastDragPosition = e.Location;
                            _currentShape.Resize(pointF);
                            Invalidate();
                            return;
                        case ShapeOperateMode.Rotote:
                            _currentShape.Rotate(e.Location);
                            LastDragPosition = e.Location;
                            Invalidate();
                            return;
                    }
                }

                #region 判断显示手柄
                //是否在矩形区域内:用于显示手柄
                bool isInRegion = false;
                foreach (ShapeBase shape in ShapeFigureList)
                {
                    rectangleF = shape.Region;
                    shape.Region = ImageConvertControlCoordinate(rectangleF);
                    if (shape.IsInRegion(e.Location))
                    {
                        this.Cursor = shape.GetSystemHandleType(e.Location);
                        isInRegion = true;
                        shape.Region = rectangleF;
                        break;
                    }
                    shape.Region = rectangleF;
                }
                if (!isInRegion) this.Cursor = Cursors.Default;
                #endregion
            }
            else
            {
                _currentShape = null;
                foreach (ShapeBase shape in ShapeFigureList)
                {
                    rectangleF = shape.Region;
                    shape.Region = ImageConvertControlCoordinate(rectangleF);
                    float dx = e.X - LastDragPosition.X;
                    float dy = e.Y - LastDragPosition.Y;
                    shape.Move(new PointF(dx, dy));
                    shape.Region = rectangleF;
                }
                Invalidate();
            }
        }
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            this.Invalidate();
            base.OnMouseWheel(e);
        }
        protected override void OnMouseDoubleClick(MouseEventArgs e)
        {
            base.OnMouseDoubleClick(e);
        }
        #endregion
    }
}
